import { Cell, Graph } from '@antv/x6'
import { InitGraphOption } from './type'
import { graphOptions } from '../config'
import { Scroller } from '@antv/x6-plugin-scroller'
import { Selection } from '@antv/x6-plugin-selection'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Clipboard } from '@antv/x6-plugin-clipboard'
import { Transform } from '@antv/x6-plugin-transform'
import mitt from 'mitt'
import { useYkEditorDrawStore } from '../store'
import { ObjectUtil } from '@utils/object-util'
import { FileUtil } from '@/utils'
import settings from '@/settings'

const store = useYkEditorDrawStore()

export function initBasicsGraphOptions (options: InitGraphOption, graphOptions: ConstructorParameters<typeof Graph>[0]) {
  if (options.json.background?.image) {
    options.json.background.image = settings.URL.IMAGE_PREFIX + options.json.background?.image
  }
  return new Graph({
    ...options.options,
    ...graphOptions,
    background: options.json.background,
    width: options.json.size.width,
    height: options.json.size.height
  })
}

export function initGraph (options: InitGraphOption) {
  const graph = initBasicsGraphOptions(options, graphOptions)
  // 安装插件
  usePlugin(graph)
  // 注册绘制时所需事件
  bindDrawingEvent(graph)
  options.json.cells && drawingGraph(graph, options.json)
  return graph
}

// region TODO 插件
// 安装插件
function usePlugin (graph: Graph) {
  useScroller(graph)
  useClipboard(graph)
  useSelection(graph)
  useTransform(graph)
  useKeyboard(graph)
}

// 安装滚动插件
function useScroller (graph: Graph) {
  const scroller = new Scroller({
    enabled: true,
    background: false,
    // modifiers: ['alt'],
    pageVisible: true,
    autoResize: false
  })
  graph.use(scroller)
}

// 安装复制粘贴插件
function useClipboard (graph: Graph) {
  const clipboard = new Clipboard({
    enabled: true
  })
  graph.use(clipboard)
}

// 安装选中插件
function useSelection (graph: Graph) {
  const selection = new Selection({
    enabled: true,
    showNodeSelectionBox: true,
    showEdgeSelectionBox: true,
    rubberband: true
  })
  graph.use(selection)
  graph.setSelectionFilter((cell) => {
    const interactingSelect = cell.data?.interactingSelect
    return store.toolbar.enableInteractingDisable ? true : interactingSelect ? !interactingSelect.disableSelect : true
  })
}

// 安装图形变换插件
function useTransform (graph: Graph) {
  const transform = new Transform({
    // 旋转手柄
    rotating: {
      enabled: true // 是否启用
    },
    // 缩放手柄
    resizing: {
      enabled: true, // 是否启用
      // 等比缩放
      preserveAspectRatio: (cell: Cell) => {
        return cell.data?.resizing?.preserveAspectRatio || false
      }
    }
  })
  graph.use(transform)
}

// 安装快捷键插件
function useKeyboard (graph: Graph) {
  const keyboard = new Keyboard({
    enabled: true
  })
  graph.use(keyboard)
  graph.bindKey('ctrl+c', () => {
    const cells = graph.getSelectedCells()
    if (cells.length) graph.copy(cells)
    return false
  })
  graph.bindKey('ctrl+x', () => {
    const cells = graph.getSelectedCells()
    if (cells.length) graph.cut(cells)
    return false
  })
  graph.bindKey('ctrl+v', () => {
    if (!graph.isClipboardEmpty()) {
      const cells = graph.paste()
      graph.clearTransformWidgets()
      // 定时器解决复制时选中节点仍使用复制的那个节点的函数，导致复制后选中的节点和操作属性面板时修改的节点不一致(主要为vue组件)
      setTimeout(() => {
        graph.cleanSelection()
        graph.select(cells)
      }, 100)
    }
    return false
  })
  graph.bindKey('ctrl+a', () => {
    graph.select(graph.getCells())
    return false
  })
  graph.bindKey(['delete', 'backspace'], () => {
    const cells = graph.getSelectedCells()
    if (cells.length) graph.removeCells(cells)
    return false
  })
}
// endregion

// region TODO 注册事件
function bindDrawingEvent (graph: Graph) {
  graph.on('cell:added', ({ cell }) => {
    const events = cell?.data?.events
    if (events) events?.added && events?.added(graph, { cell, isEdit: true })
  })
  graph.on('edge:selected', ({ cell }) => {
    store.toolbar.showEdgeTool && addEdgeTools(cell)
  })
  graph.on('edge:unselected', ({ cell }) => {
    cell.removeTools()
  })
  // document 事件
  document.onkeydown = function (event) {
    switch (event.code) {
      // 空格拖拽画布
      case 'Space':
        const scroller: Scroller = graph.getPlugin('scroller')
        const selection: Selection = graph.getPlugin('selection')
        scroller.enablePanning()
        selection.disableRubberband()
        return false
    }
  }
  document.onkeyup = function () {
    const scroller: Scroller = graph.getPlugin('scroller')
    const selection: Selection = graph.getPlugin('selection')
    scroller.disablePanning()
    selection.enableRubberband()
  }
}
// endregion

// region TODO 事件总线
export const eventBus = mitt()
// endregion

// region TODO 边线
export function addEdgeTools (cell: Cell) {
  cell.addTools([{
    name: 'source-arrowhead',
    args: {
      attrs: {
        fill: '#0006',
        stroke: '#000',
        opacity: 0.4,
        d: 'M 0 -8 -10 0 0 8 5 0 Z'
      }
    }
  }, {
    name: 'target-arrowhead',
    args: {
      attrs: {
        fill: '#f006',
        stroke: '#f00',
        opacity: 0.4
      }
    }
  }, {
    name: 'vertices',
    args: { snapRadius: 2 }
  }, 'segments'])
}
// endregion

// region TODO classUtil
export const classUtil = {
  getClassList (className: string) {
    const classList = new Set(className?.split(' ') || [])
    return {
      addClass (key: string) {
        classList.add(key)
      },
      removeClass (key: string) {
        classList.delete(key)
      },
      getClassName () {
        const classArray = Array.from(classList.values())
        return classArray.length ? classArray.join(' ') : ' '
      }
    }
  }
}
// endregion

/**
 * 根据JSON绘制内容
 * @param graph
 * @param json
 */
export function drawingGraph (graph: Graph, json: Record<string, any>) {
  graph.fromJSON(json)
  // graph.options.background = `url(${json.backgroundImage})`
  // const { container } = graph.options
  // container.style.backgroundColor = json.backgroundColor
  // container.style.backgroundImage = `url(${json.backgroundImage})`
  // const options = graph.options as any
  // options.backgroundImage = json.backgroundImage
  // options.size = {
  //   width: json.width,
  //   height: json.height
  // }
  // bindConfig(graph, graph.getCells())
}

/**
 * 保存到JSON
 * @param graph
 */
export async function saveToJSON (graph: Graph) {
  graph.cleanSelection()
  const json: any = graph.toJSON()
  json.size = store.size
  json.background = graph.options.background
  if (store.background.file) {
    await ObjectUtil.sleep(1000)
    const result = await FileUtil.updateFile(store.background.file)
    // 'https://element.eleme.cn/static/theme-index-blue.c38b733.png'
    eventBus.emit('uploadedFile', settings.URL.IMAGE_PREFIX + result)
    json.background.image = result
  }
  if (json.background.image) {
    json.background.image = json.background.image.replace(settings.URL.IMAGE_PREFIX, '')
  }
  eventBus.emit('saveGraph', json)
  return json
}
